﻿using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;

namespace AutoCADDotNetLibrary.Analyzers.Analyzers
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    public class PublicCommandAnalyzer : DiagnosticAnalyzer
    {
        public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ACDiagnostic.Rule_CommandMethodAttribute_Public);

        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.EnableConcurrentExecution();
            context.RegisterCompilationStartAction(compilationStartAnalysisContext =>
            {
                if (!Helper.GetEnableAutoCADAnalyzers(compilationStartAnalysisContext.Options))
                    return;

                List<ISymbol> errorList = new List<ISymbol>();
                compilationStartAnalysisContext.RegisterSymbolAction(symbolAnalysisContext =>
                {
                    AttributeData att = symbolAnalysisContext.Symbol.GetAttributes()
                     .Where(x => x.AttributeClass.ToDisplayString() == "Autodesk.AutoCAD.Runtime.CommandMethodAttribute").FirstOrDefault();
                    if (att == null)
                        return;

                    lock (errorList)
                    {
                        IMethodSymbol method = symbolAnalysisContext.Symbol as IMethodSymbol;
                        if (method.DeclaredAccessibility != Accessibility.Public)
                        {
                            errorList.Add(method);
                        }
                        ITypeSymbol type = method.ContainingSymbol as ITypeSymbol;
                        if (type.DeclaredAccessibility != Accessibility.Public)
                        {
                            errorList.Add(type);
                        }
                    }
                }, SymbolKind.Method);

                compilationStartAnalysisContext.RegisterCompilationEndAction(symbolAnalysisContext =>
                {
                    errorList.Distinct(SymbolEqualityComparer.Default).OrderBy(x => x is IMethodSymbol).ToList().ForEach(x =>
                    {
                        symbolAnalysisContext.ReportDiagnostic(Diagnostic.Create(ACDiagnostic.Rule_CommandMethodAttribute_Public, x.Locations.FirstOrDefault(), x.Name));
                    });
                });
            });
        }
    }
}
